import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.Timer;
import javax.swing.text.View;

import Exceptions.InternalFailureException;
import Exceptions.InvalidArgument;
import Exceptions.ParameterOutOfRangeException;
import GameElements.CTDCreep;
import GameLogic.CTDGameLogic;
import IO.*;

public class Controller implements ActionListener{

	// private TDGameWindow view = new TDGameWindow("TowerDefense");
	private CTDGameLogic model;
	private TDGameWindow view;
	private int maxX, maxY, spawn;
	/**
	 * mode 1: BuildMOde 2: SellMode 0: Normal
	 */
	private int mode;
	/**
	 * towerSelected 1: standard tower 2: aoe tower 3: splash tower 4: slow
	 * tower 5: buff tower 0: no tower
	 */
	private int towerSelected;
	private String path = "";
	private String status = "";

	private double health;
	private int gold;
	/**
	 * @return the gold
	 */
	public int getGold() {
		return (int)model.getGold();
	}
	/**
	 * @param gold the gold to set
	 */
	public void setGold(int gold) {
		model.setGold(gold);
	}
	/**
	 * @return the health
	 */
	public int getHealth() {
		return model.getPoints();
	}
	public Controller() //throws InvalidArgument
	{
		/*
		 * try { RunAction(); InitStartFrame(); UpdateView(); PickUpEndCreeps();
		 * DeadCreeps();
		 * 
		 * } catch (InvalidArgument e) { // TODO Auto-generated catch block
		 * e.printStackTrace(); }
		 */
		char[][] map = null;
		model = new CTDGameLogic();
		level _level = null;
			String testLevel = 
					"#####\n" +
			        "#___#\n" +
			        "#S>X#\n" +
			        "#___#\n" +
			        "#####\n";
			System.out.println(maxX + " " + maxY + " " + spawn);
			try {
				Generator generate = new Generator(30, 30, 4,"C:/ATI/testfile.txt");
				_level = new level(new File("C:/ATI/testfile.txt"));
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}			
			//_level = new level(testLevel);
			map = _level.returnLevel();
			//map = levelTurner(map);
			view = new TDGameWindow("Tower Defense", this);
			view.setController(this);
			ArrayList<Path> paths = _level.getPaths();
			model.LoadLevelByMapElements(map.clone());
			/*ArrayList<Path> asd = new ArrayList<Path>();
			Path path = new Path();
			path.addWaypoint( new Waypoint(1,2) );
			path.addWaypoint( new Waypoint(2, 2) );
			path.addWaypoint( new Waypoint(3, 2) );
			asd.add(path);*/
			model.InitWayPaths(_level.getPaths());
			model.Options(5, 10000, 100000, 0);
			view.setMap(map);
			/*for(int i = 0;i<map[0].length;i++)
			{
				for(int j=0;j<map.length;j++)
					System.out.print(map[j][i]);
				System.out.print('\n');
			}
			*/
		try {
			view.notifyLevelLoaded(map[0].length, map.length);
		} catch (ParameterOutOfRangeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InternalFailureException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		view.setLocationRelativeTo(null);
		view.setVisible(true);
		StartGame(30);
		ControllerThread thread = new ControllerThread();
		thread.start();
		//StartPaint(1000);
	}
	private class ControllerThread extends Thread
	{
		public void run()
		{
			while (true)
			{
				try
				{
					Thread.sleep(20);
				} catch (InterruptedException e)
				{
				}
				view.repaint();

			}
		}

	}
    private Timer timer = null;
    private Timer timer2 = null;
	public void StartGame(int delay) {
		timer  = new javax.swing.Timer( delay, new ActionListener() {
	      public void actionPerformed( ActionEvent e ) {
	    	  try {
				UpdateView();
			} catch (InvalidArgument e1) {
			}
	      }
	      });
	    timer.start();
	    timer.setRepeats(true);
	  }
	public void StartPaint(int delay) {
		timer2  = new javax.swing.Timer( delay, new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				view.repaint(1);
				
			}});
	    timer2.start();
	    timer2.setRepeats(true);
	  }
	public Controller(int width, int heigth, int spawn) //throws InvalidArgument
	{
		/*
		 * try { RunAction(); InitStartFrame(); UpdateView(); PickUpEndCreeps();
		 * DeadCreeps();
		 * 
		 * } catch (InvalidArgument e) { // TODO Auto-generated catch block
		 * e.printStackTrace(); }
		 */
		char[][] map = null;
		model = new CTDGameLogic();
		level _level = null;
		try {
			//InitStartFrame();
			System.out.println(maxX + " " + maxY + " " + spawn);
			Generator generate = new Generator(heigth, width, spawn, "C:/ATI/testfile.txt");			
			_level = new level(new File("C:/ATI/testfile.txt"));
			map = _level.returnLevel();
			//map = levelTurner(map);
			for(int i = 0;i<map[0].length;i++)
			{
				for(int j=0;j<map.length;j++)
					System.out.print(map[j][i]);
				System.out.print('\n');
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		view = new TDGameWindow("Tower Defense", this);
		view.setController(this);
		ArrayList<Path> paths = _level.getPaths();
		model.LoadLevelByMapElements(map);
		model.InitWayPaths(paths);
		model.Options(5, 100, 100000, 0);
		view.setMap(map);
		try {
			view.notifyLevelLoaded(map[0].length, map.length);
		} catch (ParameterOutOfRangeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InternalFailureException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		view.setLocationRelativeTo(null);
		view.setVisible(true);
		while(true){
			view.repaint();
			try {
				UpdateView();
			} catch (InvalidArgument e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private void RunAction() throws InvalidArgument {
		model.RunAction();

	}

	private void DeadCreeps() {
		ArrayList<CTDCreep> _creeps = model.pickUpDeadCreeps();
		/*
		 * for(int i=0;i<_creeps.size();i++)
		 * view.AddDeadCreep(_creeps.get(i).getUniqueID());
		 */
	}

	private void PickUpEndCreeps() {
		/*
		 * int[] ids = view.getEndCreeps(); if(ids == null) return;
		 * model.EndCreeps(ids);
		 */
	}

	private void UpdateView() throws InvalidArgument {
		try {
			model.UpdateWave();
			model.RunAction();
		} catch (InvalidArgument e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		ArrayList<CTDCreep> _creeps = model.getCreeps();
		 view.drawCreeps(_creeps);
	}

	private void InitModel() {
		model = new CTDGameLogic();
		model.Options(20, 1000, 1000, 0);
		model.InitWayPaths(null);
		model.InitMapElements(null);
	}

	private void InitStartFrame() {
		StartFrame sf = new StartFrame();
		sf.setVisible(true);
		while (sf.isVisible() == true) {

		}
		if (sf.getPath().equals("")) {
			maxX = sf.getMaxX();
			maxY = sf.getMaxY();
			spawn = sf.getSpawn();
		} else
			path = sf.getPath();
		// sf.dispose();
	}

	public static void main(String[] args) {
		Controller contr = new Controller();
	}

	private void BuildTower(int posX, int posY) {

	}

	void setMode(int i) {
		// TODO Auto-generated method stub
		mode = i;
	}

	/**
	 * @param towerSelected
	 *            the towerSelected to set
	 */
	public void setTowerSelected(int towerSelected) {
		this.towerSelected = towerSelected;
	}

	public void clickEntity(int x, int y) {
		int buyTower = 0;
		if (model == null)
			return;
		try {
			if (towerSelected == 1&& mode == 1) {
				buyTower = model.BuyTower(x, y, 1);
			}
			if (towerSelected == 2&& mode == 1) {
				buyTower = model.BuyTower(x, y, 2);
			}
			if (towerSelected == 3&& mode == 1) {
				buyTower = model.BuyTower(x, y, 3);
			}
			if (towerSelected == 4&& mode == 1) {
				buyTower = model.BuyTower(x, y, 4);
			}
			if (towerSelected == 5&& mode == 1) {
				buyTower = model.BuyTower(x, y, 5);
			}
			if (towerSelected == 0 && mode == 2) {
				buyTower = model.SellTower(x, y);
			}
			if(buyTower == -1){
				status = "InvalidField"; //translator
				return;}
			if(buyTower == -2){
				status = "NotEnoughMoney"; //translator
				return;}
			view.AddTower(x, y, towerSelected);
		} catch (InvalidArgument e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	
	public char[][] levelTurner(char[][] level)
	{
		for(int j = 0;j< level[0].length;j++)
		{
			for(int i=0;i<level.length;i++)
				if(level[i][j] == '<')
				{
					level[i][j] = '^';
				}
				else if(level[i][j] == '>')
				{
					level[i][j] = 'v';
				}
				else if(level[i][j] == 'v')
				{
					level[i][j] = '>';
				}
				else if(level[i][j] == '^')
				{
					level[i][j] = '<';
				}

		}
		return level;
		
	}
	@Override
	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub
		
	}
}